/*******************************************************************************
  * 文件：TM1629B.C
  * 作者：djy
  * 版本：v1.0.0
  * 日期：2020.05.29
  * 说明：TM1629B驱动程序
*******************************************************************************/
#include "TM1629B.h"

static TM1629Bright_te eBright = eBRIGHT_LEVEL_7; // 默认最亮
/*******************************************************************************
  * 函数名  ：TM1629_Delay3Nop
  * 功  能  ：TM1629延时3个nop
  * 参  数  ：U16 temp：延时temp*3个nop
  * 返回值  ：无
  * 说  明  ：显示板增加电容后，通信速率过快会失败，因此将延时一个nop改为3个
*******************************************************************************/
static void TM1629_Delay3Nop(U16 temp)
{
    U16 i;
    for(i=temp*3;i!=0;i--);
}

/*******************************************************************************
  * 函数名  ：TM1629_WriteByte
  * 功  能  ：TM1629写字节数据
  * 参  数  ：U8 u8Byte：写入的字节
  * 返回值  ：无
  * 说  明  ：无
*******************************************************************************/
static void TM1629_SendByte(U8 u8Byte)
{
    U8 u8Index;

    // 拉低片选，选中芯片
    TM1629_IO_STB = 0;
   	// 延时
	TM1629_Delay3Nop(5);
    // 设置DIO为输出模式
    TM1629_SET_DIO_OUT();
    
    // LSB-MSB输出u8Byte
    for(u8Index=0;u8Index<8;u8Index++)
    {
        // 拉低CLK
        TM1629_IO_CLK = 0;
		// 延时
		TM1629_DELAY_US(5);
        // 输出数据bit
        TM1629_IO_DIO = (u8Byte&0x01);
        // 延时
        TM1629_DELAY_US(5);
        // 置高CLK
        TM1629_IO_CLK = 1;
        // 延时
		TM1629_DELAY_US(8);
        // 右移u8Byte
        u8Byte >>= 1;
    }
	// 延时
	TM1629_Delay3Nop(5);
}

/*******************************************************************************
  * 函数名  ：TM1629_RecvByte
  * 功  能  ：TM1629读取字节数据
  * 参  数  ：无
  * 返回值  ：U8 u8Byte：写入的字节
  * 说  明  ：无
*******************************************************************************/
static U8 TM1629_RecvByte(void)
{
  	U8 u8Index;
  	U8 u8Date = 0;
	
	// 拉低片选，选中芯片
    TM1629_IO_STB = 0;
   	// 延时
	TM1629_Delay3Nop(5);
  	// 设置DIO为输入模式
    TM1629_SET_DIO_IN();
	
	for(u8Index=0;u8Index<8;u8Index++)
	{
		// 拉低CLK
		TM1629_IO_CLK = 0;
		// 右移u8Byte
		u8Date >>= 1;
		// 延时
		TM1629_DELAY_US(5);;

		// 置高CLK
		TM1629_IO_CLK = 1;
		
		// 在上升沿读取DIO数据
		if(TM1629_IO_DIO)
		{
			u8Date |= 0x80;
		}
		else
		{
			u8Date &= 0x7F;
		}
		// 延时
		TM1629_DELAY_US(8);;
	}
	// 延时
	TM1629_Delay3Nop(5);
	
	return u8Date;
}

/*******************************************************************************
  * 函数名  ：TM1629_SetBright
  * 功  能  ：TM1629设置亮度等级
  * 参  数  ：无
  * 返回值  ：无
  * 说  明  ：无
*******************************************************************************/
void TM1629_SetBright(TM1629Bright_te eTM1629Bright)
{
    if(eTM1629Bright > eBRIGHT_LEVEL_7)
    {
        eTM1629Bright = eBRIGHT_LEVEL_7;
    }

    eBright = eTM1629Bright;
    
    TM1629_SendByte(0x88 | eBright);
}

/*******************************************************************************
  * 函数名  ：TM1629_ReadKeyData
  * 功  能  ：TM1629读取按键数据
  * 参  数  ：无
  * 返回值  ：U8TM1629KeyData_tsu8Byte：读取的字节
  * 说  明  ：四个字节全部读出
*******************************************************************************/
TM1629KeyData_ts TM1629_ReadKeyData(void)
{
	U8 au8Data[4] = {0,0,0,0};
	TM1629KeyData_ts sKeyData;
	
	// 读取按键命令
    TM1629_SendByte(0x42);
	
	// 延时2us
	TM1629_DELAY_US(2);
	
    // LSB-MSB读取数据
	for(U8 u8Index=0;u8Index<4;u8Index++)
	{
		au8Data[u8Index] = TM1629_RecvByte();
	}

    // 将读出的数据复制到sKeyData
	sKeyData.uByte1.u8KeyByte = au8Data[0];
	sKeyData.uByte2.u8KeyByte = au8Data[1];
	sKeyData.uByte3.u8KeyByte = au8Data[2];
	sKeyData.uByte4.u8KeyByte = au8Data[3];
	
	// 片选置高
    TM1629_IO_STB = 1;  
    // 延时
    TM1629_Delay3Nop(1);
	
    return sKeyData;
}

/*******************************************************************************
  * 函数名  ：TM1629_WriteDisplayBytes
  * 功  能  ：TM1629写入连续数据
  * 参  数  ：U8 u8RegAddr：寄存器地址
            U8 *pu8DataAddr：待写入数据起始地址
            U8 u8Len：待写入数据长度
  * 返回值  ：无
  * 说  明  ：寄存器地址：00-0FH，数据长度最大16字节
*******************************************************************************/
void TM1629_WriteDisplayBytes(U8 u8RegAddr,U8 *pu8DataAddr,U8 u8Len)
{
    // 连续写入最多写入16Byte，寄存器地址范围0-15
    if(u8Len > 16 || u8RegAddr > 15)
    {
        return;
    }

    // 地址自增加模式，写入显示寄存器模式
    TM1629_SendByte(0x40);
    // 片选置高
    TM1629_IO_STB = 1;
	// 1us延时
    TM1629_Delay3Nop(5);
    // 寄存器起始地址
    TM1629_SendByte(0xC0 | u8RegAddr);
    // 将数据连续写入
    for(U8 u8Index=0;u8Index<u8Len;u8Index++)
    {
        TM1629_SendByte(*(pu8DataAddr+u8Index));
    }
    // 片选置高
    TM1629_IO_STB = 1;
	// 延时
    TM1629_Delay3Nop(1);
    // 开启显示，设置显示亮度
    TM1629_SendByte(0x88 | eBright);
    // 片选置高
    TM1629_IO_STB = 1;
	// 延时
    TM1629_Delay3Nop(5);
}

/*******************************************************************************
  * 函数名  ：TM1629_WriteDisplayByte
  * 功  能  ：TM1629写入单个显示寄存器数据
  * 参  数  ：U8 u8RegAddr：寄存器地址
            U8 u8Data：写入数据
  * 返回值  ：无
  * 说  明  ：寄存器地址：00-0FH
*******************************************************************************/
void TM1629_WriteDisplayByte(U8 u8RegAddr,U8 u8Data)
{
    // 寄存器地址非法
    if(u8RegAddr > 15)
    {
        return;
    }
    
    // 固定地址，写入显示寄存器
    TM1629_SendByte(0x44);
    // 片选置高
    TM1629_IO_STB = 1;
    // 延时
    TM1629_Delay3Nop(5);
    // 寄存器地址
    TM1629_SendByte(0xC0 | u8RegAddr);
    // 写入数据
    TM1629_SendByte(u8Data);
    // 片选置高
    TM1629_IO_STB = 1;    
    // 延时
    TM1629_Delay3Nop(5);
    // 开启显示，设置显示亮度
    TM1629_SendByte(0x88 | eBright);
    // TM1629_SendByte(0x8B);
    // 片选置高
    TM1629_IO_STB = 1;  
    // 延时
    TM1629_Delay3Nop(5);
}

/*******************************************************************************
  * 函数名  ：TM1629_Init
  * 功  能  ：TM1629初始化
  * 参  数  ：无
  * 返回值  ：无
  * 说  明  ：无
*******************************************************************************/
void TM1629_Init(void)
{
    TM1629_IO_STB = 1;
    TM1629_IO_CLK = 1;
    TM1629_IO_DIO = 1;
}

